package com.vf.cloud.paas.common.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.jfinal.kit.StrKit;
import com.vf.cloud.paas.common.util.ProssUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RedisServer implements Runnable {

	private String softPath;
	private String redisPort;

	public RedisServer(String softPath, int redisPort) {
		super();
		this.softPath = softPath;
		this.redisPort = redisPort + "";
	}

	@Override
	public void run() {
		try {
			ProssUtil.killByPort(redisPort);
			writeConfig();
			int status = executeCmd(
					String.format("%s/Redis/redis-server.exe %s/Redis/redis.windows.conf ", softPath, softPath));
			if (0 == status) {
				check();
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	boolean isRun = false;

	public boolean isRunning() {
		while (true) {
			try {
				if (isRun) {
					break;
				}
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return isRun;
	}

	private int executeCmd(String command) throws IOException {
		try {
			if (StrKit.isBlank(ProssUtil.getPid(redisPort))) {
				Process process = Runtime.getRuntime().exec("cmd /c start /b " + command);
				new Thread(
						new ConsoleThread(new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"))))
								.start();
				return process.waitFor();
			}
			isRun = true;
			ProssUtil.put("RedisServer", ProssUtil.getPid(redisPort));
			return 0;
		} catch (InterruptedException e) {
		}
		return -1;
	}

	/**
	 * 控制台
	 *
	 */
	class ConsoleThread implements Runnable {

		private BufferedReader bfr = null;

		public ConsoleThread(BufferedReader bfr) {
			this.bfr = bfr;
		}

		@Override
		public void run() {
			String line = null;
			try {
				while ((line = bfr.readLine()) != null) {
					log.info(line);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	private ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);

	public void check() {
		scheduledExecutor.scheduleWithFixedDelay(new TimerTask() {
			@Override
			public void run() {
				String pid = ProssUtil.getPid(redisPort);
				if (!StrKit.isBlank(pid)) {
					log.info("RedisServer >>> 启动成功，pid：" + pid);
					ProssUtil.put("RedisServer", pid);
					scheduledExecutor.shutdown();
					isRun = true;
					return;
				}
			}
		}, 0, 1, TimeUnit.SECONDS);
	}

	/**
	 * 写入配置文件
	 */
	public boolean writeConfig() {
		BufferedWriter out = null;
		try {
			File f = new File(String.format("%s/Redis/redis.windows.conf", softPath));
			if (f.exists()) {
				f.delete();
			}
			out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f, true)));
			out.write(String.format(redis_windows_conf, redisPort));
			try {
				out.close();
			} catch (IOException e) {
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e) {
			}
		}
		return false;
	}

	private String redis_windows_conf = "port %s\r\n" + 
			"tcp-backlog 511\r\n" + 
			"bind 0.0.0.0\r\n" + 
			"timeout 0\r\n" + 
			"tcp-keepalive 0\r\n" + 
			"loglevel notice\r\n" + 
			"logfile \"\"\r\n" + 
			"databases 16\r\n" + 
			"save \"\"\r\n" + 
			"stop-writes-on-bgsave-error yes\r\n" + 
			"rdbcompression yes\r\n" + 
			"rdbchecksum yes\r\n" + 
			"dbfilename dump.rdb\r\n" + 
			"dir ./\r\n" + 
			"slave-serve-stale-data yes\r\n" + 
			"slave-read-only yes\r\n" + 
			"repl-diskless-sync no\r\n" + 
			"repl-diskless-sync-delay 5\r\n" + 
			"repl-disable-tcp-nodelay no\r\n" + 
			"slave-priority 100\r\n" + 
			"appendonly no\r\n" + 
			"appendfilename \"appendonly.aof\"\r\n" + 
			"appendfsync everysec\r\n" + 
			"no-appendfsync-on-rewrite no\r\n" + 
			"auto-aof-rewrite-percentage 100\r\n" + 
			"auto-aof-rewrite-min-size 64mb\r\n" + 
			"aof-load-truncated yes\r\n" + 
			"lua-time-limit 5000\r\n" + 
			"slowlog-log-slower-than 10000\r\n" + 
			"slowlog-max-len 128\r\n" + 
			"latency-monitor-threshold 0\r\n" + 
			"notify-keyspace-events \"\"\r\n" + 
			"hash-max-ziplist-entries 512\r\n" + 
			"hash-max-ziplist-value 64\r\n" + 
			"list-max-ziplist-entries 512\r\n" + 
			"list-max-ziplist-value 64\r\n" + 
			"set-max-intset-entries 512\r\n" + 
			"zset-max-ziplist-entries 128\r\n" + 
			"zset-max-ziplist-value 64\r\n" + 
			"hll-sparse-max-bytes 3000\r\n" + 
			"activerehashing yes\r\n" + 
			"client-output-buffer-limit normal 0 0 0\r\n" + 
			"client-output-buffer-limit slave 256mb 64mb 60\r\n" + 
			"client-output-buffer-limit pubsub 32mb 8mb 60\r\n" + 
			"hz 10\r\n" + 
			"aof-rewrite-incremental-fsync yes";

}
